In [1]:
function steps(n)
root = ceil(sqrt(n))
curR = root % 2 != 0 ? root : root + 1
numR = (curR - 1) / 2
cycle = n - ((curR - 2) ^ 2)
innerOffset = cycle % (curR - 1)
numR + abs(innerOffset - numR)
end
Out[1]:
In [2]:
steps(23)
Out[2]:
In [3]:
steps(12)
Out[3]:
In [4]:
@time steps(347991)
Out[4]:
Code taken from Ferran solution and translated to Julia :-P
In [5]:
function number_to_coordinates(n)
q = floor(sqrt(n))
r = n - q ^ 2
if q % 2 != 0
x = div(q - 1, 2) + min(1, r) + min(q - r + 1, 0)
y = - div(q - 1, 2) + min(max(r - 1, 0), q)
else
x = 1 - div(q, 2) - min(1, r) - min(q - r + 1, 0)
y = div(q, 2) - min(max(r - 1, 0), q)
end
[x, y]
end
function spiral_manhattan(n)
x, y = number_to_coordinates(n)
abs(x) + abs(y)
end
Out[5]:
In [6]:
function spiral_coordinates(c::Channel)
n = 0
while n >= 0
n += 1
put!(c, number_to_coordinates(n))
end
end
Out[6]:
In [7]:
using DataStructures
function first_larger(bound)
values = DefaultDict(0)
g = Channel(spiral_coordinates)
pos = take!(g)
values[pos] = 1
while values[pos] <= bound
pos = take!(g)
values[pos] = sum( values[pos + [i, j]] for i=-1:1 for j=-1:1 if i!=0||j!=0 )
end
values[pos]
end
Out[7]:
In [8]:
first_larger(22)
Out[8]:
In [9]:
@time first_larger(347991)
Out[9]: